﻿using System;
using System.Collections;
using System.ComponentModel;
using System.Drawing;
using System.Reflection;
using System.Windows.Forms;

namespace HML
{
    /// <summary>
    /// ToolTipPlus提示控件
    /// </summary>
    [Description("ToolTipPlus提示控件")]
    [DefaultProperty("TitleVisible")]
    [DefaultEvent("Popup")]
    [TypeConverter(typeof(PropertyOrderConverter))]
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(ToolTipPlus), "Controls.ToolTipPlus.Resources.ToolTipPlus.bmp")]
    public class ToolTipPlus : ToolTip, ISkinObject
    {
        #region 主题

        private SkinObjectXmlMetadata skinObjectXmlMetadata = null;
        /// <summary>
        /// 主题对象在主题文件信息
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual SkinObjectXmlMetadata SkinObjectXmlMetadata
        {
            get
            {
                if (this.skinObjectXmlMetadata == null)
                    this.skinObjectXmlMetadata = new SkinObjectXmlMetadata(Assembly.GetAssembly(typeof(ToolTipPlus)).GetName().Name, typeof(ToolTipPlus).Name);

                return this.skinObjectXmlMetadata;
            }
        }

        private SkinController skinController = null;
        /// <summary>
        /// 主题控制器
        /// </summary>
        [Description("主题控制器")]
        [Category("杂项")]
        [PropertyOrder(-360)]
        [DefaultValue(null)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinController SkinController
        {
            get { return this.skinController; }
            set
            {
                if (this.skinController == value)
                    return;

                if (this.skinController != null)
                    this.skinController.RemoveSkinObject(this);

                this.skinController = value;

                if (this.skinController != null)
                    this.skinController.AddSkinObject(this);
            }
        }

        private SkinEnabledState skinEnabled= SkinEnabledState.Auto;
        /// <summary>
        /// 主题是否启用
        /// </summary>
        [Description("主题是否启用")]
        [Category("杂项")]
        [PropertyOrder(-300)]
        [DefaultValue(SkinEnabledState.Auto)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinEnabledState SkinEnabled
        {
            get { return this.skinEnabled; }
            set
            {
                if (this.skinEnabled == value)
                    return;

                this.skinEnabled = value;
                this.OnSkinChanged();
            }
        }

        private SkinStyle skinStyle = SkinStyle.Normal;
        /// <summary>
        /// 主题风格
        /// </summary>
        [Description("主题风格")]
        [Category("杂项")]
        [PropertyOrder(-260)]
        [DefaultValue(SkinStyle.Normal)]
        [RefreshProperties(RefreshProperties.All)]
        public virtual SkinStyle SkinStyle
        {
            get { return this.skinStyle; }
            set
            {
                if (this.skinStyle == value)
                    return;

                this.skinStyle = value;
                this.OnSkinChanged();
            }
        }

        private StyleAppearanceObject stateAppearance;
        /// <summary>
        /// 风格外观
        /// </summary>
        [Description("风格外观")]
        [Category("杂项")]
        [PropertyOrder(-200)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public StyleAppearanceObject StyleAppearance
        {
            get
            {
                if (this.stateAppearance == null)
                    this.stateAppearance = new StyleAppearanceObject(this, null);
                return this.stateAppearance;
            }
        }

        /// <summary>
        /// 主题已更改
        /// </summary>
        public virtual void OnSkinChanged()
        {
            SkinManager.SyncSkinValueToProperty(this);

        }

        private ISkinObject followSkinObject = null;
        /// <summary>
        /// 主题设置跟随指定主题对象（自己的设置不再生效，提供给代码使用）
        /// </summary>
        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        [Localizable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public virtual ISkinObject FollowSkinObject
        {
            get { return this.followSkinObject; }
            set
            {
                if (this.followSkinObject == value)
                    return;

                this.followSkinObject = value;
                this.OnSkinChanged();
            }
        }

        public virtual bool GetSkinObjectSkinStateCore()
        {
            return SkinManager.GetSkinObjectSkinState(this.FollowSkinObject ?? this);
        }

        void ISkinObject.InitializeInvalidate()
        {
            throw new NotImplementedException();
        }

        void ISkinObject.Invalidate()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region 新增属性

        private ToolTipPlusAnchors anchor = ToolTipPlusAnchors.TopCenter;
        /// <summary>
        /// 提示框出现位置
        /// </summary>
        [Description("提示框出现位置")]
        [Category("杂项")]
        [PropertyOrder(-199)]
        [Browsable(false)]
        [DefaultValue(ToolTipPlusAnchors.TopCenter)]
        public ToolTipPlusAnchors Anchor
        {
            get { return this.anchor; }
            set
            {
                if (this.anchor == value)
                    return;

                this.anchor = value;
            }
        }

        private int anchorSpace = 20;
        /// <summary>
        /// 提示框出现位置与拥有者的距离(只限于 Show 方法有效)
        /// </summary>
        [Description("提示框出现位置与拥有者的距离(只限于 Show 方法有效)")]
        [Category("杂项")]
        [PropertyOrder(-198)]
        [DefaultValue(20)]
        public int AnchorSpace
        {
            get { return this.anchorSpace; }
            set
            {
                if (this.anchorSpace == value || value < 0)
                    return;

                this.anchorSpace = value;
            }
        }

        private Size maxSize = new Size(0, 0);
        /// <summary>
        /// 最大Size
        /// </summary>
        [Description("最大Size")]
        [Category("杂项")]
        [PropertyOrder(-196)]
        [DefaultValue(typeof(Size), "0, 0")]
        public Size MaxSize
        {
            get { return this.maxSize; }
            set
            {
                if (this.maxSize == value)
                    return;

                this.maxSize = value;
                Size size_tmp = this.minSize;
                if (this.maxSize.Width != 0 && this.minSize.Width != 0 && this.minSize.Width > this.maxSize.Width)
                {
                    size_tmp.Width = this.maxSize.Width;
                }
                if (this.maxSize.Height != 0 && this.minSize.Height != 0 && this.minSize.Height > this.maxSize.Height)
                {
                    size_tmp.Height = this.maxSize.Height;
                }
                this.minSize = size_tmp;
            }
        }

        private Size minSize = new Size(0, 0);
        /// <summary>
        /// 最小Size
        /// </summary>
        [Description("最小Size")]
        [Category("杂项")]
        [PropertyOrder(-194)]
        [DefaultValue(typeof(Size), "0,0")]
        public Size MinSize
        {
            get { return this.minSize; }
            set
            {
                if (this.minSize == value)
                    return;

                this.minSize = value;

                Size size_tmp = this.maxSize;
                if (this.minSize.Width != 0 && this.maxSize.Width != 0 && this.maxSize.Width < this.minSize.Width)
                {
                    size_tmp.Width = this.minSize.Width;
                }
                if (this.minSize.Height != 0 && this.maxSize.Height != 0 && this.maxSize.Height < this.minSize.Height)
                {
                    size_tmp.Height = this.minSize.Height;
                }
                this.maxSize = size_tmp;
            }
        }

        private Font font = null;
        /// <summary>
        /// 文本字体
        /// </summary>
        [Description("文本字体")]
        [Category("杂项")]
        [PropertyOrder(-193)]
        public Font Font
        {
            get
            {
                if (this.font != null)
                {
                    return this.font;
                }
                return Control.DefaultFont;
            }
            set
            {
                if (Control.DefaultFont.Equals(value))
                {
                    this.font = null;
                    return;
                }

                this.font = value;
            }
        }
        private bool ShouldSerializeFont()
        {
            return (this.font != null && !this.font.Equals(Control.DefaultFont));
        }
        private void ResetFont()
        {
            this.font = null;
        }

        private bool borderVisible = true;
        /// <summary>
        /// 是否显示边框
        /// </summary>
        [Description("是否显示边框")]
        [Category("杂项")]
        [PropertyOrder(-192)]
        [DefaultValue(true)]
        public bool BorderVisible
        {
            get { return this.borderVisible; }
            set
            {
                if (this.borderVisible == value)
                    return;

                this.borderVisible = value;
            }
        }

        private bool titleVisible = false;
        /// <summary>
        /// 是否显示标题
        /// </summary>
        [Description("是否显示标题")]
        [Category("杂项")]
        [PropertyOrder(-180)]
        [DefaultValue(false)]
        public bool TitleVisible
        {
            get { return this.titleVisible; }
            set
            {
                if (this.titleVisible == value)
                    return;

                this.titleVisible = value;
            }
        }

        private ToolTipPlusTitleLayouts titleLayout = ToolTipPlusTitleLayouts.Top;
        /// <summary>
        /// 提示框标题布局
        /// </summary>
        [Description("提示框标题布局")]
        [PropertyOrder(-178)]
        [DefaultValue(ToolTipPlusTitleLayouts.Top)]
        public ToolTipPlusTitleLayouts TitleLayout
        {
            get { return this.titleLayout; }
            set
            {
                if (this.titleLayout == value)
                    return;

                this.titleLayout = value;
            }
        }

        private string title = "";
        /// <summary>
        /// 标题
        /// </summary>
        [Description("标题")]
        [Category("杂项_标题")]
        [PropertyOrder(-176)]
        [DefaultValue("")]
        public string Title
        {
            get { return this.title; }
            set
            {
                if (this.title == value)
                    return;

                this.title = value;
            }
        }

        #endregion

        #region 重写属性

        [Category("杂项")]
        [PropertyOrder(-220)]
        public new bool ShowAlways
        {
            get { return base.ShowAlways; }
            set { base.ShowAlways = value; }
        }
        [Category("杂项")]
        [PropertyOrder(-218)]
        public new bool Active
        {
            get { return base.Active; }
            set { base.Active = value; }
        }

        [Category("杂项")]
        [PropertyOrder(-216)]
        public new bool UseAnimation
        {
            get { return base.UseAnimation; }
            set { base.UseAnimation = value; }
        }

        [Category("杂项")]
        [PropertyOrder(-214)]
        public new bool UseFading
        {
            get { return base.UseFading; }
            set { base.UseFading = value; }
        }

        [Category("杂项")]
        [PropertyOrder(-212)]
        public new int AutomaticDelay
        {
            get { return base.AutomaticDelay; }
            set { base.AutomaticDelay = value; }
        }

        [Category("杂项")]
        [PropertyOrder(-210)]
        public new int InitialDelay
        {
            get { return base.InitialDelay; }
            set { base.InitialDelay = value; }
        }

        [Category("杂项")]
        [PropertyOrder(-208)]
        public new int ReshowDelay
        {
            get { return base.ReshowDelay; }
            set { base.ReshowDelay = value; }
        }

        [Category("杂项")]
        [PropertyOrder(-206)]
        public new int AutoPopDelay
        {
            get { return base.AutoPopDelay; }
            set { base.AutoPopDelay = value; }
        }

        [Category("杂项")]
        [PropertyOrder(-204)]
        public new bool StripAmpersands
        {
            get { return base.StripAmpersands; }
            set { base.StripAmpersands = value; }
        }

        #endregion

        #region 停用属性

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new bool IsBalloon
        {
            get { return base.IsBalloon; }
            set { base.IsBalloon = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new ToolTipIcon ToolTipIcon
        {
            get { return base.ToolTipIcon; }
            set { base.ToolTipIcon = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new string ToolTipTitle
        {
            get { return base.ToolTipTitle; }
            set { base.ToolTipTitle = value; }
        }

        [Browsable(false)]
        [EditorBrowsable(EditorBrowsableState.Never)]
        public new bool OwnerDraw
        {
            get { return base.OwnerDraw; }
            set { base.OwnerDraw = value; }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Color BackColor
        {
            get { return this.StyleAppearance.BackColor; }
            set { }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new Color ForeColor
        {
            get { return this.StyleAppearance.TextColor; }
            set { }
        }

        #endregion

        #region 字段

        /// <summary>
        /// 内容内边距
        /// </summary>
        private int cententPadding = 1;

        #endregion

        public ToolTipPlus()
        {
            this.OwnerDraw = true;
            this.Popup += new PopupEventHandler(this.ToolTipPlus_Popup);
            this.Draw += new System.Windows.Forms.DrawToolTipEventHandler(this.ToolTipPlus_Draw);

            this.OnSkinChanged();
        }

        public ToolTipPlus(IContainer container) : this()
        {
            if (container == null)
            {
                throw new ArgumentNullException("container");
            }

            container.Add(this);
        }

        #region 公开方法

        /// <summary>
        /// 设置与指定控件关联的工具提示文本，然后在指定的相对位置以模式方式显示该工具提示。
        /// </summary>
        /// <param name="text">包含新工具提示文本的 System.String。</param>
        /// <param name="window">要为其显示工具提示的 System.Windows.Forms.Control。</param>
        /// <param name="rect">重新定义关联控件窗口的rect信息( Rectangle.Empty 值时不会重新定义)</param>
        /// <param name="anchor">工具提示的位置</param>
        public void Show(string text, IWin32Window window, Rectangle rect, ToolTipPlusAnchors anchor)
        {
            this.anchor = anchor;
            Control control = (Control)window;
            if (rect == Rectangle.Empty)
            {
                rect.Width = control.Width;
                rect.Height = control.Height;
            }

            Size size = this.GetControlAutoSize(control, text);
            Point point = new Point(0, 0);
            if (this.Anchor == ToolTipPlusAnchors.TopCenter)
            {
                point = new Point(rect.X + (rect.Width - size.Width) / 2, rect.Y - this.AnchorSpace - size.Height);
            }
            else if (this.Anchor == ToolTipPlusAnchors.BottomCenter)
            {
                point = new Point(rect.X + (rect.Width - size.Width) / 2, rect.Bottom + this.AnchorSpace);
            }
            else if (this.Anchor == ToolTipPlusAnchors.LeftCenter)
            {
                point = new Point(rect.X - (size.Width + this.AnchorSpace), rect.Y + (rect.Height - size.Height) / 2);
            }
            else if (this.Anchor == ToolTipPlusAnchors.RightCenter)
            {
                point = new Point(rect.Right + this.AnchorSpace, rect.Y + (rect.Height - size.Height) / 2);
            }
            this.Show(text, window, point);
        }

        /// <summary>
        /// 设置与指定控件关联的工具提示文本，然后在指定的相对位置以模式方式显示该工具提示。
        /// </summary>
        /// <param name="text">包含新工具提示文本的 System.String。</param>
        /// <param name="window">要为其显示工具提示的 System.Windows.Forms.Control。</param>
        /// <param name="rect">重新定义关联控件窗口的rect信息</param>
        /// <param name="anchor">工具提示的位置</param>
        /// <param name="duration">包含工具提示持续显示时间（以毫秒为单位）的 System.Int32。</param>
        public void Show(string text, IWin32Window window, Rectangle rect, ToolTipPlusAnchors anchor, int duration)
        {
            this.anchor = anchor;
            Control control = (Control)window;
            if (rect == Rectangle.Empty)
            {
                rect.X = control.Location.X;
                rect.Y = control.Location.Y;
                rect.Width = control.Width;
                rect.Height = control.Height;
            }

            Size size = this.GetControlAutoSize(control, text);
            Point point = new Point(0, 0);
            if (this.Anchor == ToolTipPlusAnchors.TopCenter)
            {
                point = new Point(rect.X + (rect.Width - size.Width) / 2, rect.Y - this.AnchorSpace - size.Height);
            }
            else if (this.Anchor == ToolTipPlusAnchors.BottomCenter)
            {
                point = new Point(rect.X + (rect.Width - size.Width) / 2, rect.Bottom + this.AnchorSpace);
            }
            else if (this.Anchor == ToolTipPlusAnchors.LeftCenter)
            {
                point = new Point(rect.X - (size.Width + this.AnchorSpace), rect.Y + (rect.Height - size.Height) / 2);
            }
            else if (this.Anchor == ToolTipPlusAnchors.RightCenter)
            {
                point = new Point(rect.Right + this.AnchorSpace, rect.Y + (rect.Height - size.Height) / 2);
            }
            this.Show(text, window, point, duration);
        }

        #endregion

        #region 私有方法

        private void ToolTipPlus_Popup(object sender, PopupEventArgs e)
        {
            e.ToolTipSize = this.GetControlAutoSize(e.AssociatedControl);
        }

        private void ToolTipPlus_Draw(object sender, DrawToolTipEventArgs e)
        {
            //背景
            SolidBrush back_sb = new SolidBrush(this.BackColor);
            e.Graphics.FillRectangle(back_sb, e.Bounds);
            back_sb.Dispose();

            //标题
            Rectangle title_back_rect = new Rectangle();
            if (this.TitleVisible)
            {
                Font title_font = new Font(this.Font.FontFamily, this.Font.Size + 1);
                int title_back_height = (int)(title_font.Height * 140 / 100f);
                PointF title_text_point = new PointF();
                StringFormat title_text_sf = (StringFormat)StringFormat.GenericTypographic.Clone();
                if (this.TitleLayout == ToolTipPlusTitleLayouts.Left || this.TitleLayout == ToolTipPlusTitleLayouts.Right)
                {
                    title_text_sf.FormatFlags = StringFormatFlags.DirectionVertical;
                }
                Size title_text_size = Size.Ceiling(e.Graphics.MeasureString(this.Title, title_font, int.MaxValue, title_text_sf));

                if (this.TitleLayout == ToolTipPlusTitleLayouts.Top)
                {
                    title_back_rect = new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width, title_back_height);
                    title_text_point = new PointF(title_back_rect.X + this.cententPadding, title_back_rect.Y + (title_back_rect.Height - title_text_size.Height) / 2f + title_text_size.Height / 10f);
                }
                else if (this.TitleLayout == ToolTipPlusTitleLayouts.Bottom)
                {
                    title_back_rect = new Rectangle(e.Bounds.X, e.Bounds.Bottom - title_back_height, e.Bounds.Width, title_back_height);
                    title_text_point = new PointF(title_back_rect.X + this.cententPadding, e.Bounds.Bottom - title_back_rect.Height + (title_back_rect.Height - title_text_size.Height) / 2 + title_text_size.Height / 10f);
                }
                else if (this.TitleLayout == ToolTipPlusTitleLayouts.Left)
                {
                    title_back_rect = new Rectangle(e.Bounds.X, e.Bounds.Y, title_back_height, e.Bounds.Height);
                    title_text_point = new PointF(title_back_rect.X + (title_back_rect.Width - title_text_size.Width) / 2 + title_text_size.Width / 12f, title_back_rect.Y + this.cententPadding);
                }
                else if (this.TitleLayout == ToolTipPlusTitleLayouts.Right)
                {
                    title_back_rect = new Rectangle(e.Bounds.Right - title_back_height, e.Bounds.Y, title_back_height, e.Bounds.Height);
                    title_text_point = new PointF(title_back_rect.Right - title_back_rect.Width + (title_back_rect.Width - title_text_size.Width) / 2 + title_text_size.Width / 12f, title_back_rect.Y + this.cententPadding);
                }

                SolidBrush title_back_sb = new SolidBrush(this.StyleAppearance.TitleBackColor);
                e.Graphics.FillRectangle(title_back_sb, title_back_rect);
                title_back_sb.Dispose();

                SolidBrush title_text_sb = new SolidBrush(this.StyleAppearance.TitleTextColor);
                e.Graphics.DrawString(this.Title, title_font, title_text_sb, title_text_point.X, title_text_point.Y, title_text_sf);
                title_text_sb.Dispose();
                title_text_sf.Dispose();

                title_font.Dispose();
            }

            // 内容
            Size content_text_size = Size.Ceiling(e.Graphics.MeasureString(e.ToolTipText, this.Font, int.MaxValue, StringFormat.GenericTypographic));
            Rectangle content_text_rect = new Rectangle();
            if (this.TitleLayout == ToolTipPlusTitleLayouts.Top)
            {
                content_text_rect = new Rectangle(e.Bounds.X + this.cententPadding, title_back_rect.Bottom + this.cententPadding, e.Bounds.Width - this.cententPadding * 2, e.Bounds.Height - title_back_rect.Height - this.cententPadding * 2);
            }
            else if (this.TitleLayout == ToolTipPlusTitleLayouts.Bottom)
            {
                content_text_rect = new Rectangle(e.Bounds.X + this.cententPadding, e.Bounds.Y + this.cententPadding, e.Bounds.Width - this.cententPadding * 2, e.Bounds.Height - title_back_rect.Height - this.cententPadding * 2);
            }
            else if (this.TitleLayout == ToolTipPlusTitleLayouts.Left)
            {
                content_text_rect = new Rectangle(e.Bounds.X + title_back_rect.Width + this.cententPadding, e.Bounds.Y + this.cententPadding, e.Bounds.Width - title_back_rect.Height - this.cententPadding * 2, e.Bounds.Height - this.cententPadding * 2);
            }
            else if (this.TitleLayout == ToolTipPlusTitleLayouts.Right)
            {
                content_text_rect = new Rectangle(e.Bounds.X + this.cententPadding, e.Bounds.Y + this.cententPadding, e.Bounds.Width - title_back_rect.Height - this.cententPadding * 2, e.Bounds.Height - this.cententPadding * 2);
            }

            Region source_r = e.Graphics.Clip;
            Region content_r = new Region(content_text_rect);
            e.Graphics.Clip = content_r;

            SolidBrush text_sb = new SolidBrush(this.StyleAppearance.TextColor);
            e.Graphics.DrawString(e.ToolTipText, this.Font, text_sb, content_text_rect);
            text_sb.Dispose();

            e.Graphics.Clip = source_r;
            content_r.Dispose();

            //边框
            if (this.BorderVisible)
            {
                Pen border_pen = new Pen(this.StyleAppearance.BorderColor);
                e.Graphics.DrawRectangle(border_pen, new Rectangle(e.Bounds.X, e.Bounds.Y, e.Bounds.Width - 1, e.Bounds.Height - 1));
                border_pen.Dispose();
            }

        }

        /// <summary>
        /// 通过文本计算工具提示大小(text为null时根据control的提示文本计算)
        /// </summary>
        /// <param name="control">要为其检索 System.Windows.Forms.ToolTip 文本的 System.Windows.Forms.Control。</param>
        /// <param name="text">要计算的指定文本</param>
        /// <param name="title">要计算的标题</param>
        /// <returns></returns>
        private Size GetControlAutoSize(Control control, string text = null, string title = null)
        {
            IDpiControl tmp = control as IDpiControl;
            float dpi = tmp == null ? 1f : tmp.ScaleDpi;

            IntPtr hDC;
            Graphics g;
            ControlHelper.GetWindowClientGraphics(control.Handle, out g, out hDC);

            string text_str = (text == null ? this.GetToolTip(control) : text);
            Size text_size = Size.Ceiling(g.MeasureString(text_str, this.Font, int.MaxValue, StringFormat.GenericDefault));
            text_size.Width += this.cententPadding * 2;
            text_size.Height += this.cententPadding * 2;

            Size title_size = Size.Empty;
            if (this.TitleVisible)
            {
                string title_str = (title == null ? this.Title : title);
                Font title_font = new Font(this.Font.FontFamily, this.Font.Size + 1);
                if (String.IsNullOrWhiteSpace(title_str))
                {
                    title_size = new Size(0, (int)(title_font.Height * 140 / 100f));
                }
                else
                {
                    title_size = Size.Ceiling(g.MeasureString(title_str, title_font, int.MaxValue, StringFormat.GenericTypographic));
                    title_size.Height = (int)(title_size.Height * 140 / 100f);
                }
                if (this.TitleLayout == ToolTipPlusTitleLayouts.Left || this.TitleLayout == ToolTipPlusTitleLayouts.Right)
                {
                    title_size.Width = (int)(title_size.Height * 140 / 100f);
                }
                title_font.Dispose();
            }

            g.Dispose();
            NativeMethods.ReleaseDC(control.Handle, hDC);

            Size control_size;
            if (this.TitleLayout == ToolTipPlusTitleLayouts.Top || this.TitleLayout == ToolTipPlusTitleLayouts.Bottom)
            {
                control_size = new Size(Math.Max(text_size.Width, title_size.Width), title_size.Height + text_size.Height);
            }
            else
            {
                control_size = new Size(title_size.Height + text_size.Width, Math.Max(text_size.Height, title_size.Width));
            }

            if (this.MinSize.Width > 0 && this.MinSize.Width > text_size.Width)
            {
                control_size.Width = (int)(this.MinSize.Width * dpi);
            }
            if (this.MinSize.Height > 0 && this.MinSize.Height > text_size.Height)
            {
                control_size.Height = (int)(this.MinSize.Height * dpi);
            }
            if (this.MaxSize.Width > 0 && text_size.Width > this.MaxSize.Width)
            {
                control_size.Width = (int)(this.MaxSize.Width * dpi);
            }
            if (this.MaxSize.Height > 0 && text_size.Height > this.MaxSize.Height)
            {
                control_size.Height = (int)(this.MaxSize.Height * dpi);
            }

            return control_size;
        }

        #endregion

        #region 外观

        public class StyleAppearanceObject : AppearanceObjectBase
        {
            internal StyleAppearanceObject(ISkinObject owner, AppearanceObjectBase parent) : base(owner, parent) { }

            #region 属性

            private Color skinBorderColor = Color.Empty;
            private readonly Color defaultBorderColor = SystemColors.ActiveCaption;
            private Color borderColor = Color.Empty;
            /// <summary>
            /// 边框颜色
            /// </summary>
            [Description("边框颜色")]
            [PropertyOrder(-159)]
            [SkinProperty(true, false)]
            public Color BorderColor
            {
                get
                {
                    if (this.borderColor != Color.Empty)
                    {
                        return this.borderColor;
                    }

                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinBorderColor;
                    }

                    return this.defaultBorderColor;
                }
                set
                {
                    if (this.borderColor == value)
                        return;

                    this.borderColor = value;
                }
            }
            private bool ShouldSerializeBorderColor()
            {
                return this.borderColor != Color.Empty;
            }
            private void ResetBorderColor()
            {
                this.borderColor = Color.Empty;
            }

            private Color skinBackColor = Color.Empty;
            private readonly Color defaultBackColor = SystemColors.Info;
            private Color backColor = Color.Empty;
            /// <summary>
            /// 背景颜色
            /// </summary>
            [Description("背景颜色")]
            [PropertyOrder(-158)]
            [SkinProperty(true, false)]
            public Color BackColor
            {
                get
                {
                    if (this.backColor != Color.Empty)
                    {
                        return this.backColor;
                    }

                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinBackColor;
                    }

                    return this.defaultBackColor;
                }
                set
                {
                    if (this.backColor == value)
                        return;

                    this.backColor = value;
                }
            }
            private bool ShouldSerializeBackColor()
            {
                return this.backColor != Color.Empty;
            }
            private void ResetBackColor()
            {
                this.backColor = Color.Empty;
            }

            private Color skinTextColor = Color.Empty;
            private readonly Color defaultTextColor = SystemColors.InfoText;
            private Color textColor = Color.Empty;
            /// <summary>
            /// 文本颜色
            /// </summary>
            [Description("文本颜色")]
            [PropertyOrder(-157)]
            [SkinProperty(true, false)]
            public Color TextColor
            {
                get
                {
                    if (this.textColor != Color.Empty)
                    {
                        return this.textColor;
                    }

                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinTextColor;
                    }

                    return this.defaultTextColor;
                }
                set
                {
                    if (this.textColor == value)
                        return;

                    this.textColor = value;
                }
            }
            private bool ShouldSerializeTextColor()
            {
                return this.textColor != Color.Empty;
            }
            private void ResetTextColor()
            {
                this.textColor = Color.Empty;
            }


            private Color skinTitleBackColor = Color.Empty;
            private readonly Color defaultTitleBackColor = SystemColors.GradientActiveCaption;
            private Color titleBackColor = Color.Empty;
            /// <summary>
            /// 标题背景颜色
            /// </summary>
            [Description("标题背景颜色")]
            [PropertyOrder(-174)]
            [SkinProperty(true, false)]
            public Color TitleBackColor
            {
                get
                {
                    if (this.titleBackColor != Color.Empty)
                    {
                        return this.titleBackColor;
                    }

                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinTitleBackColor;
                    }

                    return this.defaultTitleBackColor;
                }
                set
                {
                    if (this.titleBackColor == value)
                        return;

                    this.titleBackColor = value;
                }
            }
            private bool ShouldSerializeTitleBackColor()
            {
                return this.titleBackColor != Color.Empty;
            }
            private void ResetTitleBackColor()
            {
                this.titleBackColor = Color.Empty;
            }

            private Color skinTitleTextColor = Color.Empty;
            private readonly Color defaultTitleTextColor = SystemColors.ActiveCaption;
            private Color titleTextColor = Color.Empty;
            /// <summary>
            /// 标题文本颜色
            /// </summary>
            [Description("标题文本颜色")]
            [PropertyOrder(-172)]
            [SkinProperty(true, false)]
            public Color TitleTextColor
            {
                get
                {
                    if (this.titleTextColor != Color.Empty)
                    {
                        return this.titleTextColor;
                    }

                    if (this.owner.GetSkinObjectSkinStateCore())
                    {
                        return this.skinTitleTextColor;
                    }

                    return this.defaultTitleTextColor;
                }
                set
                {
                    if (this.titleTextColor == value)
                        return;

                    this.titleTextColor = value;
                }
            }
            private bool ShouldSerializeTitleTextColor()
            {
                return this.titleTextColor != Color.Empty;
            }
            private void ResetTitleTextColor()
            {
                this.titleTextColor = Color.Empty;
            }

            #endregion

        }

        #endregion

    }

}
